﻿--版本控制：1.2.0
local AddonName, Addon = ...

local L = Addon.L

local GetTime = GetTime
local GetSpellInfo = GetSpellInfo
local GetNumGroupMembers = GetNumGroupMembers
local IsInRaid = IsInRaid
local UnitIsDead = UnitIsDead
local UnitIsUnit = UnitIsUnit
local IsSpellInRange = IsSpellInRange
local CheckInteractDistance = CheckInteractDistance
local UnitGUID = UnitGUID
local UnitName = UnitName
local UnitInRaid = UnitInRaid
local UnitClass = UnitClass
local UnitHealth = UnitHealth
local UnitHealthMax = UnitHealthMax
local UnitInRange = UnitInRange
local UnitIsFriend = UnitIsFriend
local UnitIsDeadOrGhost = UnitIsDeadOrGhost
local PlaySoundFile = PlaySoundFile
local GetRealZoneText = GetRealZoneText
local UnitAffectingCombat = UnitAffectingCombat
local CombatLogGetCurrentEventInfo = CombatLogGetCurrentEventInfo
local UnitDetailedThreatSituation = UnitDetailedThreatSituation

local Task = {}
local BossSpellList = {}
local RealTarget = ""
local Mirror = 0
local CTPhase = 0
local CurrentTarget = ""

local LastScan = 0
local LastCheck = 0

local PlayerName = ""

Addon.Frame:RegisterEvent("ADDON_LOADED")
Addon.Frame:RegisterEvent("PLAYER_LOGOUT")
Addon.Frame:RegisterEvent("CHAT_MSG_MONSTER_EMOTE")
Addon.Frame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
Addon.Frame:RegisterEvent("UNIT_TARGET")
Addon.Frame:RegisterEvent("PLAYER_REGEN_DISABLED")
Addon.Frame:RegisterEvent("UNIT_THREAT_LIST_UPDATE")
Addon.Frame:RegisterEvent("UNIT_HEALTH")

--方法函数：更新表
function Addon:UpdateConfig(Target, Source)
	for k, v in pairs(Source) do
		if type(v) == "table" then
			if type(Target[k]) == "table" then
				self:UpdateConfig(Target[k], v)
			else
				Target[k] = self:UpdateConfig({}, v)
			end
		elseif type(Target[k]) ~= "table" then
			Target[k] = v
		end
	end
	return Target
end

--方法函数，获取CID
function Addon:GetCIDFromGUID(guid)
	local type, _, playerdbID, _, _, cid, creationbits = strsplit("-", guid or "")
	if type and (type == "Creature" or type == "Vehicle" or type == "Pet") then
		return tonumber(cid)
	end
	return 0
end

--方法函数：设置延时任务
function Addon:SetWarningTask(TaskName, Files, Delay)
    local TimeStamp = math.floor(GetTime()*1000)

    for i = 1, #Task do
        if TaskName == Task[i].Name then
            Task[i].TimeStamp = TimeStamp
            Task[i].Delay = Delay
            return
        end
    end

    if Delay > 0.1 then
        local CacheTask = {}
        CacheTask["Name"] = TaskName
        CacheTask["TimeStamp"] = TimeStamp
        CacheTask["Delay"] = Delay
        CacheTask["Action"] = Files

        table.insert(Task, CacheTask)
    end
end

--获取Spell信息
function Addon:InitSpellNameByID()
    -- 预言者
    BossSpellList["MindControl"] = GetSpellInfo(785) -- 充实
    BossSpellList["ArcaneExplosion"] = GetSpellInfo(26192) -- 奥爆
    BossSpellList["Summon"] = GetSpellInfo(747) -- 召唤幻象
    -- 维希度斯
    BossSpellList["Rejoin"] = GetSpellInfo(25869) -- 召唤维希度斯水滴
    -- 哈霍兰
    BossSpellList["Berserk"] = GetSpellInfo(26051)
    -- 双子
    BossSpellList["Teleport"] = GetSpellInfo(799) -- 双子传送
    BossSpellList["ShadowBolt"] = GetSpellInfo(26006) -- 暗影箭
    -- 奥罗
    BossSpellList["Knockback"] = GetSpellInfo(26103) -- 横扫
    -- 克苏恩
    BossSpellList["EyeBeam"] = GetSpellInfo(26134) -- 眼棱
    BossSpellList["Birth"] = GetSpellInfo(26586) -- 出生
    BossSpellList["Acid"] = GetSpellInfo(26476) -- 消化酸液
    -- 5狗头
    BossSpellList["Plague"] = GetSpellInfo(22997) -- 瘟疫
end
--事件处理分配
Addon.Frame:SetScript("OnEvent", function(self, event, ...)
--  print(event)
    if type(self[event]) == "function" then
        return self[event](self, ...)
    end
end)

--延时任务处理
Addon.Frame:SetScript("OnUpdate", function(self, lastupdate)
    if Addon.Config.IsEnable == "off" then
        Addon.Frame:Hide()
        return
    end
    if not GetRealZoneText() == L["Ahn'Qiraj"] then
        return
    end
    if not IsInRaid() then
        return
    end
    if next(Task) == nil then
        return
    end

    local NowScan = math.floor(GetTime()*10)/10
    if NowScan == LastScan then
        return
    end
    LastScan = NowScan

	if #Task > 0 then
		for i = #Task, 1, -1 do
            if NowScan >= Task[i].TimeStamp/1000 + Task[i].Delay then
                local Character = Addon.Config.SelectSound
                PlaySoundFile(L["SOUND_PATH"]..Character..Task[i].Action, Addon.Config.OutputChannel)
                if Task[i].Name == "DarkGlare" and CTPhase == 1 then
                    Task[i].TimeStamp = math.floor(GetTime()*1000)
                    Task[i].Delay = 84
                else
                    table.remove(Task, i)
                end
			end
		end
	end

    if (UnitAffectingCombat("player") or not UnitIsDeadOrGhost("player")) and CTPhase == 1 then
        if NowScan >= LastCheck then
            for i = 1, GetNumGroupMembers() do
                if CheckInteractDistance("raid"..i, 3) and not UnitIsDeadOrGhost("raid"..i) and not UnitIsUnit("player", "raid"..i) then
                    local Character = Addon.Config.SelectSound
                    PlaySoundFile(L["SOUND_PATH"]..Character.."\\CThun_10Yards.mp3", Addon.Config.OutputChannel)
                    break
                end
            end
            LastCheck = NowScan + 5
        end
    end

end)

function Addon.Frame:ADDON_LOADED(...)
	local arg = {...}
	if arg[1] == AddonName then
		--加载提示
    	self:UnregisterEvent("ADDON_LOADED") --完成加载后反注册事件
    	if not SoundTAQDB then
            SoundTAQDB = {
                ["Config"] = {},
                ["CharacterList"] = {}
            }
        end
        if not SoundTAQDB.Config then
            SoundTAQDB.Config = {}
        end
        if not SoundTAQDB.CharacterList then
            SoundTAQDB.CharacterList = {}
        end
        Addon:UpdateConfig(Addon.Config, SoundTAQDB.Config)
        Addon:UpdateConfig(Addon.CharacterList, SoundTAQDB.CharacterList)
        if Addon.Config.IsEnable and not Addon.Frame:IsShown() then
            Addon.Frame:Show()
        end
        Addon.Panel:Initialize()
        Addon:InitSpellNameByID()
        PlayerName = UnitName("player")
        print(string.format(L["SOUNDTAQ_LOAD"], Addon.Version))
	end
end

function Addon.Frame:PLAYER_LOGOUT()
    SoundTAQDB = {
        ["Config"] = {},
        ["CharacterList"] = {}
    }
    Addon:UpdateConfig(SoundTAQDB.Config, Addon.Config)
    Addon:UpdateConfig(SoundTAQDB.CharacterList, Addon.CharacterList)
end

function Addon.Frame:CHAT_MSG_MONSTER_EMOTE(...)
    if Addon.Config.IsEnable == "off" then
        return
    end
    if not GetRealZoneText() == L["Ahn'Qiraj"] then
        return
    end
    if not IsInRaid() then
        return
    end

    local arg = {...}
    local Character = Addon.Config.SelectSound

    if arg[2] == L["Viscidus"] then
        if string.find(arg[1],L["is freezing up"]) then
            if UnitClass("player") == L["Warrior"] or UnitClass("player") == L["Rogue"] or UnitClass("player") == L["Hunter"] then
                PlaySoundFile(L["SOUND_PATH"]..Character.."\\Viscidus_Prepare.mp3", Addon.Config.OutputChannel)
            end
        end
    end
end

function Addon.Frame:COMBAT_LOG_EVENT_UNFILTERED(...) --TAQ专有DEBUFF提示
    if Addon.Config.IsEnable == "off" then
        return
    end
    if not GetRealZoneText() == L["Ahn'Qiraj"] then
        return
    end
    if not IsInRaid() then
        return
    end

	local arg ={CombatLogGetCurrentEventInfo()} --COMBAT_LOG_EVENT_UNFILTERED 事件参数
    local Character = Addon.Config.SelectSound

    if arg[2] == "SPELL_AURA_APPLIED" then
        if arg[13] == BossSpellList["MindControl"] then
            local unit = "raid"..UnitInRaid(arg[9])
            if UnitClass("player") == L["Mage"] and CheckInteractDistance("player", unit) and not UnitIsUnit("player", unit) then
                PlaySoundFile(L["SOUND_PATH"]..Character.."\\Skeram_Control.mp3", Addon.Config.OutputChannel)
            end
        elseif arg[13] == BossSpellList["Plague"] and arg[9] == PlayerName then
            PlaySoundFile(L["SOUND_PATH"]..Character.."\\Five_Plague.mp3", Addon.Config.OutputChannel)
        elseif arg[13] == BossSpellList["Teleport"] then
            if UnitClass("player") == L["Priest"] or UnitClass("player") == L["Druid"] or UnitClass("player") == L["Paladin"] or UnitClass("player") == L["Shaman"] then
                PlaySoundFile(L["SOUND_PATH"]..Character.."\\Empires_Teleport.mp3", Addon.Config.OutputChannel)
            end
        end
    elseif arg[2] == "SPELL_CAST_START" then
        if arg[5] == L["The Prophet Skeram"] and arg[13] == BossSpellList["ArcaneExplosion"] then
            if UnitClass("player") == L["Warrior"] or UnitClass("player") == L["Rogue"] or UnitClass("player") == L["Mage"] or UnitClass("player") == L["Shaman"] then
                PlaySoundFile(L["SOUND_PATH"]..Character.."\\Skeram_Interrupt.mp3", Addon.Config.OutputChannel)
            end
        elseif arg[5] == L["Giant Eye Tentacle"] and arg[13] == BossSpellList["EyeBeam"] then
            if UnitClass("player") == L["Warrior"] or UnitClass("player") == L["Rogue"] or UnitClass("player") == L["Mage"] or UnitClass("player") == L["Shaman"] then
                PlaySoundFile(L["SOUND_PATH"]..Character.."\\CThun_Interrupt.mp3", Addon.Config.OutputChannel)
            end
        elseif arg[5] == L["Ouro"] and arg[13] == BossSpellList["Knockback"] then
            if UnitClass("player") == L["Warrior"] or UnitClass("player") == L["Rogue"] then
                PlaySoundFile(L["SOUND_PATH"]..Character.."\\Ouro_Knockback.mp3", Addon.Config.OutputChannel)
            end
        end
    elseif arg[2] == "SPELL_CAST_SUCCESS" then
        local cid = Addon:GetCIDFromGUID(arg[4])
        if cid == 15726 and arg[13] == BossSpellList["Birth"] then
            if CTPhase == 1 then
                Addon:SetWarningTask("EyeTentacleP1", "\\CThun_EyeTentacle.mp3", 42)
            elseif CTPhase == 2 then
                Addon:SetWarningTask("EyeTentacleP2", "\\CThun_EyeTentacle.mp3", 28)
            end
        elseif cid == 15667 and arg[13] == BossSpellList["Rejoin"] then
            for i = #Task, 1, -1 do
                if Task[i].Name == "Viscidus" then
                    table.remove(Task, i)
                    break
                end
            end
        elseif arg[5] == L["Princess Huhuran"] and arg[13] == BossSpellList["Berserk"] then
            if UnitClass("player") == L["Hunter"] then
                PlaySoundFile(L["SOUND_PATH"]..Character.."\\Huhuran_Tranquilizing.mp3", Addon.Config.OutputChannel)
            end
        end
    elseif arg[2] == "UNIT_DIED" then
        local Type = strsplit("-", arg[8] or "")
        if Type == "Creature" and Addon:GetCIDFromGUID(arg[8]) == 15589 then
            CTPhase = 2
            Addon:SetWarningTask("EyeTentacleP2", "\\CThun_EyeTentacle.mp3", 38)
            for i = #Task, 1, -1 do
                if Task[i].Name == "DarkGlare" or Task[i].Name == "EyeTentacleP1" then
                    table.remove(Task, i)
                    break
                end
            end
        elseif Type == "Creature" and Addon:GetCIDFromGUID(arg[8]) == 15263 and arg[8] ~= RealTarget then
            Mirror = Mirror - 1
        elseif Type == "Creature" and arg[8] == RealTarget then
            Mirror = 0
        end
    elseif arg[2] == "SWING_DAMAGE" then
        if arg[9] == L["Princess Huhuran"] then
            local unit = ""
            if UnitName("target") == L["Princess Huhuran"] then
                unit = "target"
            elseif UnitName("targettarget") == L["Princess Huhuran"] then
                unit = "targettarget"
            elseif UnitName("mouseover") == L["Princess Huhuran"] then
                unit = "mouseover"
            end
            if UnitHealth(unit)/UnitHealthMax(unit) > 0.3 and UnitHealth(unit)/UnitHealthMax(unit) < 0.35 then
                if UnitClass("player") == L["Priest"] or UnitClass("player") == L["Shaman"] then
                    PlaySoundFile(L["SOUND_PATH"]..Character.."\\Huhuran_Berserk.mp3", Addon.Config.OutputChannel)
                end
            end
        elseif arg[9] == L["Viscidus"] then
            if arg[13] and tonumber(arg[13]) > 0 then
                Addon:SetWarningTask("Viscidus", "\\Viscidus_AOE.mp3", 10.5)
            end
        end
    elseif arg[2] == "SPELL_AURA_APPLIED_DOSE" then
        if arg[13] == BossSpellList["Acid"] and arg[9] == PlayerName then
            if arg[16] >= 7 then
                PlaySoundFile(L["SOUND_PATH"]..Character.."\\CThun_GetOut.mp3", Addon.Config.OutputChannel)
            end
        end
    elseif arg[2] == "SPELL_SUMMON" then
        if arg[13] == BossSpellList["Summon"] then
            Mirror = 2
        end
    elseif string.find(arg[2], "DAMAGE") and not string.find(arg[2], "SWING") and arg[9] == L["Viscidus"] then
        if arg[16] and tonumber(arg[16]) > 0 then
            Addon:SetWarningTask("Viscidus", "\\Viscidus_AOE.mp3", 10.5)
        end
    end
end

function Addon.Frame:PLAYER_REGEN_DISABLED()
    if Addon.Config.IsEnable == "off" then
        return
    end
    if not GetRealZoneText() == L["Ahn'Qiraj"] then
        return
    end
    if not IsInRaid() then
        return
    end

    for i = 1, GetNumGroupMembers() do
        local u = "raid"..i
        if UnitName(u) and UnitName(u.."target") and not UnitIsFriend(u, u.."target") then
            local guid = UnitGUID(u.."target")
            if Addon:GetCIDFromGUID(guid) == 15589 and CTPhase ~= 1 and not UnitIsDead(u.."target") then
                CTPhase = 1
                Addon:SetWarningTask("DarkGlare", "\\CThun_DarkGlare.mp3", 46)
                Addon:SetWarningTask("EyeTentacleP1", "\\CThun_EyeTentacle.mp3", 42)
                break
            elseif Addon:GetCIDFromGUID(guid) == 15727 and CTPhase ~= 2 and UnitIsDead(u.."target") then
                CTPhase = 2
                break
            elseif Addon:GetCIDFromGUID(guid) == 15263 and not UnitIsDead(u.."target") then
                Mirror = 0
                break
            end
        end
    end
end

function Addon.Frame:UNIT_TARGET(unit)
    if Addon.Config.IsEnable == "off" then
        return
    end
    if not GetRealZoneText() == L["Ahn'Qiraj"] then
        return
    end
    if not IsInRaid() then
        return
    end
    if unit ~= "player" then
        return
    end

    local Character = Addon.Config.SelectSound

    if UnitName("target") == L["The Prophet Skeram"] then
        if UnitHealth("target")/UnitHealthMax("target") > 0.8 and RealTarget ~= UnitGUID("target") then
            RealTarget = UnitGUID("target")
        elseif RealTarget == UnitGUID("target") and Mirror > 0 then
            PlaySoundFile(L["SOUND_PATH"]..Character.."\\Skeram_WrongTarget.mp3", Addon.Config.OutputChannel)
        end
    end
end

function Addon.Frame:UNIT_THREAT_LIST_UPDATE(...)
    if Addon.Config.IsEnable == "off" then
        return
    end
    if not GetRealZoneText() == L["Ahn'Qiraj"] then
        return
    end
    if not IsInRaid() then
        return
    end

    local HostileUnit = ""
    if UnitName("target") == L["Emperor Vek'lor"] then
        HostileUnit = "target"
    elseif UnitName("targettarget") == L["Emperor Vek'lor"] then
        HostileUnit = "targettarget"
    end

    if HostileUnit == "" then
        return
    end

    local Character = Addon.Config.SelectSound

    for i = 1, GetNumGroupMembers() do
        local IsTanking = UnitDetailedThreatSituation("raid"..i, HostileUnit)
        if IsTanking and UnitClass("raid"..i) == L["Warlock"] and CurrentTarget == "Other" then
            CurrentTarget = "Warlock"
            if (UnitClass("player") == L["Priest"] or UnitClass("player") == L["Druid"] or UnitClass("player") == L["Paladin"] or UnitClass("player") == L["Shaman"]) and UnitInRange("raid"..i) then
                PlaySoundFile(L["SOUND_PATH"]..Character.."\\Empires_Threat.mp3", Addon.Config.OutputChannel)
                break
            end
        else
            CurrentTarget = "Other"
        end
    end
end